package com.aote.rs;

import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;

import com.af.plugins.Base64Utils;
import com.af.plugins.RSAUtil;
import com.aote.rs.helper.CharacterSetHelper;
import com.aote.rs.mapper.WebException;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.log4j.Logger;

import com.browsesoft.Entity;
import com.browsesoft.EntityManager;
import com.browsesoft.dbtools.DBTools;
import com.browsesoft.resource.BasicResource;
import com.browsesoft.resource.LicensePolicyTool;
import com.browsesoft.user.User;
import org.springframework.stereotype.Component;

@Path("user")
@Component
public class UserService {
	static Logger log = Logger.getLogger(UserService.class);

	@GET
	@Path("systime")
	public String getTime() {
		long time = new Date().getTime();
		return "" + time;
	}

	@SuppressWarnings("finally")
	@Path("/modifypwd")
	@POST
	public String modifyPwd(@Context HttpServletRequest request, String send) {
		String result = "true";
		try {
			JSONObject sendJson = JSONObject.fromObject(send);
			String sendData = sendJson.get("data").toString();
			Hashtable data = this.convert(sendData);
			String ename = data.get("ename") + "";
			User user = (User) EntityManager.getInstance().getUserForLoginName(
					ename);
			String oldpwd = data.get("password") + "";
			String newpwd = data.get("newpassword") + "";
			String affirmPass = data.get("affirmpassword") + "";
			user.modifyPassword(oldpwd, newpwd, affirmPass);
		} catch (Exception e) {
			result = "操作失败" + e.getMessage() + "";
			throw new RuntimeException(e);
		} finally {
			return result;
		}
	}

	private Hashtable convert(String data) {
		data = CharacterSetHelper.restDecode(data);
		JSONObject obj = JSONObject.fromObject(data);
		Hashtable result = jsonToHash(obj);
		return result;
	}
	@GET
	@Path("{username}")
	public String getUser(@PathParam("username") String name) {
		try {
			User user = (User) EntityManager.getInstance().getUserForLoginName(
					name);
			String result = getUserString(user);
			log.debug(result);
			return result;
		} catch (Exception e) {
			throw new WebApplicationException(e);
		}
	}

	@GET
	@Path("{username}/{password}")
	// 根据用户名密码获取用户信息
	public String getUserWithPass(@PathParam("username") String name,
			@PathParam("password") String password,
			@Context HttpServletRequest request) {
		try {
			User user = (User) EntityManager.getInstance().getUserForLoginName(
					name);
			String userpass = (String) user.attributes.get("password");
			log.debug("系统中登记的用户密码: " + userpass);
			// 密码不同，抛出密码错误异常
			if (!password.equals(userpass)) {
				throw new WebApplicationException(401);
			}
			String ip=getClientIp(request);
			user.getAttributes().put("loginip", ip);
			String result = getUserString(user, null);
			log.debug(result);
			return result;
		} catch (WebApplicationException e) {
			throw e;
		} catch (Exception e) {
			throw new WebApplicationException(e);
		}
	}




	@GET
	@Path("{username}/{password}/{module}/{ip}")
	public String getUserWithPassIP(@PathParam("username") String name,
			@PathParam("password") String password,
			@PathParam("module") String module,
			@Context HttpServletRequest request) {
		try {
			User user = EntityManager.getInstance().getUser(name, password,
					isCase());

			if (user == null) {
				throw new WebApplicationException(401);
			}
			String ip=getClientIp(request);
			user.getAttributes().put("loginip", ip);
			String result = getUserString(user, module);
			log.debug(result);
			return result;
		} catch (WebApplicationException e) {
			throw e;
		} catch (Exception e) {
			throw new WebApplicationException(e);
		}
	}

   	//登录函数
	@POST
	@Path("userLogin/{module}")
	public String userLogin(@PathParam("module") String module, String str, @Context HttpServletRequest request) {
		try {
			// 对传过来的数据解密
			str = RSAUtil.descrypt(str);
			JSONObject data = JSONObject.fromObject(str);
		  	String name =  data.get("username") + "";
			String password = data.get("password")+"";

			log.debug("解密完成：name=" + name + ", password=" + password + ", module=" + module);
			User user = EntityManager.getInstance().getUser(name, password,
					isCase());
			if (user == null) {
				throw new WebApplicationException(401);
			}
			// 检查用户是否已登录，2分钟内没有访问，表示用户已经退出
			String ip=getClientIp(request);
			checkLogin(user, ip);

			user.getAttributes().put("loginip", ip);
			// 设置用户初始心跳时间
			user.getAttributes().put("accesstime", new Date().getTime() + "");
			String result = getUserString(user, module);
			log.debug(result);
			// 保存用户登录信息
			user.update();
			return result;
		} catch (WebApplicationException e) {
			throw e;
		} catch (WebException e) {
			throw e;
		} catch (Exception e) {
			throw new WebApplicationException(e);
		}
	}

	/**
	 * 看用户是否已登录，如果心跳时间在2分钟内，则证明已登录
	 * @param user
	 * @return
	 */
	private void checkLogin(User user, String ip) {
		String accesstime = (String)user.getAttributes().get("accesstime");
		// 如果没有最后访问时间，说明未登录，
		if (accesstime == null) {
			return;
		}

		// ip相同，允许登录
		if (ip.equals(user.getAttributes().get("loginip"))) {
			return;
		}

		long last = Long.parseLong(accesstime);
		long now = new Date().getTime();

		if (now - last < 2 * 60 * 1000) {
			throw new WebException(710, "用户已登录");
		}
	}

	/**
	 * 接收心跳信息，前台2分钟发送一次心跳
	 */
	@GET
	@Path("access/{userid}")
	public void access(@PathParam("userid") String userid) throws Exception {
		User user = EntityManager.getInstance().getUserById(userid);
		if (user == null) {
			throw new WebException(720, "心跳信息错误");
		}
		// 设置用户初始心跳时间
		user.getAttributes().put("accesstime", new Date().getTime() + "");
		user.update();
	}

	@Deprecated
	/**
	 * Description 过期登录函数，原因：get方法不支持请求中特殊字符，改为post
	 * 新函数:  userLogin
	 */
	@GET
	@Path("{username}/{password}/{module}")
	// 获取某个登录用户，指定模块的数据
	public String getUserWithPass(@PathParam("username") String name,
			@PathParam("password") String password,
			@PathParam("module") String module,
			@Context HttpServletRequest request) {
		try {
			User user = (User) EntityManager.getInstance().getUser(name,
					password, isCase());
			// 密码不同，抛出密码错误异常
			if (user == null) {
				throw new WebApplicationException(401);
			}
			String ip=getClientIp(request);
			user.getAttributes().put("loginip", ip);
			String result = getUserString(user, module);
			log.debug(result);
			return result;
		} catch (WebApplicationException e) {
			throw e;
		} catch (Exception e) {
			throw new WebApplicationException(e);
		}
	}

	//从请求中获取ip，如果请求没有，从转发服务器参数获取
	
	private String  getClientIp(@Context HttpServletRequest request)
	{
		String ip = null;
		if(request.getHeader("X-Real-IP")!=null){
			ip = request.getHeader("X-Real-IP");
		}else{
			ip = request.getRemoteAddr();
		}
	    return ip;
	}
		
		
	@POST
	@Path("/entity")
	public String save(String data) {
		log.debug(data);
		System.out.println("保存用户：+++"+data);
		try {
			// 解析数据，根据id得到对象，更新属性
			JSONArray array = JSONArray.fromObject(data);
			JSONObject obj = (JSONObject) array.iterator().next();
			JSONObject dataObj = obj.getJSONObject("data");
			Hashtable newAttrs = this.jsonToHash(dataObj);
			String id = (String) newAttrs.get("id");
			Entity entity = (Entity) EntityManager.getInstance().getObject(id);
			if (entity == null) {
				throw new WebApplicationException(500);
			}
			entity.getAttributes().putAll(newAttrs);
			entity.update();
			return obj.toString();
		} catch (Exception e) {
			throw new WebApplicationException(500);
		}
	}

	/**
	 * json数据转map
	 */
	private Hashtable jsonToHash(JSONObject obj) {
		Hashtable result = new Hashtable();
		Iterator iter = obj.keySet().iterator();
		while (iter.hasNext()) {
			String key = iter.next().toString();
			String value = obj.getString(key);
			if (value != null & !value.equals("null")) {
				key = key.toLowerCase();
				result.put(key, value);
			}
		}
		return result;
	}

	/**
	 * 看是否区分大小写
	 * 
	 * @param
	 * @return
	 */
	private boolean isCase() {
		try {
			// 取出设置的是否区分大小写属性
			String sql = "select f_matchcase from t_setpassrule";
			String[][] temp = DBTools.executeQueryWithTableHead(sql);
			return temp[1][0].equals("区分大小写");
		} catch (Exception ex) {
			return false;
		}
	}

	// 获取用户信息，只获取指定模块的信息
	public String getUserString(User user, String module) {
		log.debug("********in getUserString********");

		// 获得用户权限，包括用户所属组
		Collection rs = LicensePolicyTool.getRights(user, "function");
		log.debug("有权访问的功能：" + rs);
		// 对获得的权限进行处理，去掉父关系，保留子关系，以便Json转换，集合中保留最上层的父
        Map<String, Object> root = getResourceTree(module, rs);
		LinkedList orgList = new LinkedList();
		// 从根元素中
		Map<String, Object> map = new HashMap<String, Object>(user.attributes);
		// 去掉密码
        map.remove("password");

		map.put("functions", root.get("children"));
		map.put("rolesnames", user.getRolesStr());
		// 循环设置父对象
		BasicResource parent = (BasicResource) user.getParent();
		System.out.println(parent.attributes.get("name"));
		if (parent != null) {
			Map parentMap = getMap(parent.attributes);
			orgList.add(parentMap);
		}
		Map ht = map;
		// 拼接组织结构
		String orgFullPath = "";
		String orgPathIds = "";
		// 当前登录人
		String filialePath = "";
		String filialeIds = "";
		while (parent != null) {
			Map parentMap = getMap(parent.attributes);
			ht.put("parent", parentMap);
			ht = parentMap;
			parent = (BasicResource) parent.getParent();
			if (parent != null
					&& !parent.attributes.get("name").equals("统一资源管理(网络)")) {
				Map attrs = getMap(parent.attributes);
				orgList.add(attrs);
			}
		}
		for (int i = orgList.size(); i > 0; i--) {
			Map orgMap = (HashMap) orgList.get(i - 1);
			String orgName = orgMap.get("name").toString();
			String orgId = orgMap.get("id").toString();
			orgFullPath = orgFullPath + orgName + ".";
			orgPathIds = orgPathIds + orgId + ".";
			if ("公司".equals((String)(orgMap.get("f_companylevel")))) {
				filialePath = filialePath + orgName + ".";
				filialeIds = filialeIds + orgId + ".";
			}
		}
		if (orgFullPath.endsWith(".")) {
			orgFullPath = orgFullPath.substring(0, orgFullPath.length() - 1);
		}
		if (orgPathIds.endsWith(".")) {
			orgPathIds = orgPathIds.substring(0, orgPathIds.length() - 1);
		}
		if (filialePath.endsWith(".")) {
			filialePath = filialePath.substring(0, filialePath.length() - 1);
		}
		if (filialeIds.endsWith(".")) {
			filialeIds = filialeIds.substring(0, filialeIds.length() - 1);
		}

		// 去掉前面两个节点
		int pos = orgFullPath.indexOf('.');
		pos = orgFullPath.indexOf('.', pos + 1);
		orgFullPath = orgFullPath.substring(pos + 1);
		pos = orgPathIds.indexOf('.');
		pos = orgPathIds.indexOf('.', pos + 1);
		orgPathIds = orgPathIds.substring(pos + 1);
		log.debug("orgpathstr:" + orgPathIds + ",orgpathnames" + orgFullPath);
		// 在orgpath* 后添加登录用户的信息
		((Map) map).put("orgpathstr", orgPathIds + "." + user.getID() + ".");
		((Map) map).put("orgpathnames", orgFullPath + "." + user.getName());
		((Map) map).put("filialestr", filialeIds);
		((Map) map).put("filialenames", filialePath);

		// 返回公司及部门名称，临时用，以后会废弃
		String f_fengongsi = user.getInfo().getString("orgs");
		map.put("f_fengongsi", f_fengongsi);
		String orgids = user.getInfo().getString("orgids");
		map.put("f_orgids", orgids);
		map.put("f_parentname", ((BasicResource) user.getParent()).attributes.get("name"));

		String result = JSONObject.fromObject(map).toString();
		return result;
	}

    /**
     * 从有权访问的功能中，取得给定模块的功能树
     * @param module
     * @param rs
     * @return
     */
    private Map<String, Object> getResourceTree(String module, Collection rs) {
        Map<String, Object> root = null;
        for (BasicResource func : getRoot(rs)) {
            String name = (String)func.attributes.get("name");
            log.debug("module=" + module + ", name=" + name);
            // 如果与给定模块名称相同, 或者未限定模块
            if (module == null || name.equals(module)) {
                root = getMap(func, rs);
                break;
            }
        }
        if (root == null) {
            throw new WebApplicationException(500);
        }
        return root;
    }

    /**
	 * 取得用户所属部门名称
	 * @param user
	 * @return
	 */
	private String getDept(User user) {
		BasicResource resource = (BasicResource) user.getParentByType("department");
		if (resource == null) {
			return "";
		}
		String name = (String)resource.attributes.get("name");
		return name;
	}

	// 获取资源的一般属性，不包括对象关系属性
	private Map getMap(Hashtable attrs) {
		Map result = new HashMap();
		Enumeration en = attrs.keys();
		while (en.hasMoreElements()) {
			Object key = en.nextElement();
			Object value = attrs.get(key);
			if (value.getClass().isPrimitive() || value instanceof String) {
				result.put(key, value);
			}
		}
		return result;
	}

	// 获取用户信息
	public String getUserString(User user) {
		// 获得用户权限，包括用户所属组
		Collection rs = LicensePolicyTool.getRights(user, "function");
		// 对获得的权限进行处理，去掉父关系，保留子关系，以便Json转换，集合中保留最上层的父
		LinkedList funcs = new LinkedList();
		for (BasicResource func : getRoot(rs)) {
			funcs.add(getMap(func, rs));
		}
		Map<String, Object> map = new HashMap<String, Object>(user.attributes);
		map.put("functions", funcs);
		map.put("rolesnames", user.getRolesStr());
		String result = JSONObject.fromObject(map).toString();
		return result;
	}

	// 获得第一层功能列表
	public LinkedList<BasicResource> getRoot(Collection rs) {
		LinkedList<BasicResource> result = new LinkedList<BasicResource>();
		for (Object obj : rs) {
			BasicResource func = (BasicResource) obj;
			// 父不在这个集合中，就是根
			if (!rs.contains(func.getParent())) {
				result.add(func);
			}
		}
		return result;
	}

	// 处理一个功能项，把子添加到自己的属性子中，并且把所有子删除掉，要递归调用
	public Map<String, Object> getMap(BasicResource func, Collection rs) {
		Map<String, Object> result = new HashMap<String, Object>(
				func.attributes);
		// 获得该功能项有权访问的子
		LinkedList list = new LinkedList(func.getChildrenByType("function"));
		list.retainAll(rs);
		// 只有属性的子列表
		LinkedList attrList = new LinkedList();
		for (Object obj : list) {
			BasicResource f = (BasicResource) obj;
			Map<String, Object> child = getMap(f, rs);
			attrList.add(child);
		}
		// 设置子
		if (!attrList.isEmpty()) {
			result.put("children", attrList);
		}
		return result;
	}
}
